package com.yn.common.config.web;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yn.common.utils.ex.BaseErrorEnum;
import com.yn.common.utils.ex.BusinessException;
import com.yn.common.utils.web.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashSet;
import java.util.Set;

/**
 * @description: 统一响应处理
 * @author: zq
 * @create: 2022/3/29 11:00
 * @since: 1.0.0
 * @copyright (C), 2020, 北京望海康信科技有限公司.All rights reserved.
 */
@RestControllerAdvice(basePackages = "com.yn", annotations = {Controller.class, RestController.class})
@Slf4j
public class WebResponseHandler implements ResponseBodyAdvice<Object> {
    private static ObjectMapper Object_Mapper = new ObjectMapper();

    /**
     * 如果接口返回的类型本身就是JsonOut那就没有必要进行额外的操作，返回false
     * 注意：统一处理需要放行swagger相关内容
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {
        Set<String> swaggerTypes = new HashSet<>();
        swaggerTypes.add("org.springframework.http.ResponseEntity<java.util.List<springfox.documentation.swagger.web" +
                ".SwaggerResource>>");
        swaggerTypes.add("org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json>");
        swaggerTypes.add("org.springframework.http.ResponseEntity<springfox.documentation.swagger.web" +
                ".UiConfiguration>");
        return !(swaggerTypes.contains(returnType.getGenericParameterType().getTypeName())
                || returnType.getParameterType().equals(R.class));
    }


    @Override
    public Object beforeBodyWrite(Object objData, MethodParameter returnType, MediaType mediaType, Class<?
            extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
        // 返回类型为json，所以String类型不能直接封装，需要进行特殊处理
        if (String.class.equals(returnType.getGenericParameterType())) {
            // 如果返回String，那么肯定是retMessage
            try {
                return Object_Mapper.writeValueAsString(R.success().data(objData));
            } catch (JsonProcessingException e) {
                throw new BusinessException(BaseErrorEnum.CHECK_PARAMS_ERR.getCode(), BaseErrorEnum.CHECK_PARAMS_ERR.getMessage());
            }
        }
        /* 如果使用封装类R，那么说明，需要重写处理成功的提示 */
        return R.success().data(objData);
    }
}
